﻿using System;

namespace ASPItalia.ModelVirtualCasting.Random
{
    internal abstract class RandomNumberGeneratorBase : IRandomNumberGenerator
    {
        private const int MIN_LENGTH = 1;
        private const int MAX_LENGTH = 16384;

        public int Generate(int lowerBound, int upperBound)
        {
            int randomNumber = 0;

            lowerBound = Math.Abs(lowerBound);
            upperBound = Math.Abs(upperBound);

            if (lowerBound == upperBound)
                return lowerBound;

            if (lowerBound < upperBound)
            {
                try
                {
                    randomNumber = this.GenerateSingleNumber(lowerBound, upperBound);
                }
                catch (Exception ex)
                {
                    ExceptionLogWriter.Write("RandomNumberGeneratorBase.Generate", ex);
                }
            }

            return randomNumber;
        }

        public int[] Generate(int lowerBound, int upperBound, int length)
        {
            if ((length < MIN_LENGTH) || (length > MAX_LENGTH))
                return new int[0];

            lowerBound = Math.Abs(lowerBound);
            upperBound = Math.Abs(upperBound);

            if (lowerBound > upperBound)
                return new int[0];

            int[] randomNumbers = new int[length];

            for (int i = 0; i < length; i++)
            {
                if (lowerBound == upperBound)
                {
                    randomNumbers[i] = lowerBound;
                }
                else
                {
                    try
                    {
                        randomNumbers[i] = this.GenerateSingleNumber(lowerBound, upperBound);
                    }
                    catch (Exception ex)
                    {
                        ExceptionLogWriter.Write("RandomNumberGeneratorBase.Generate", ex);
                        break;
                    }
                }
            }

            return randomNumbers;
        }

        public double Generate()
        {
            double value = default(double);

            try
            {
                value = this.GenerateSingleDouble();
            }
            catch (Exception ex)
            {
                ExceptionLogWriter.Write("RandomNumberGeneratorBase.Generate", ex);
            }

            return value;
        }

        public double[] Generate(int length)
        {
            if ((length < MIN_LENGTH) || (length > MAX_LENGTH))
                return new double[0];

            double[] randomValues = new double[length];

            for (int i = 0; i < length; i++)
            {
                try
                {
                    randomValues[i] = this.GenerateSingleDouble();
                }
                catch (Exception ex)
                {
                    ExceptionLogWriter.Write("RandomNumberGeneratorBase.Generate", ex);
                    break;
                }
            }

            return randomValues;
        }

        protected abstract int GenerateSingleNumber(int lowerBound, int upperBound);
        protected abstract double GenerateSingleDouble();
    }
}
